import numpy as np
from math import sqrt,pi,sin,cos,atan2

def length(vector):
    result=0
    for v in np.nditer(vector):
        result+=v**2
    return sqrt(result)    

# 利用点积提取三维向量在给定方向上的分量
# 我们可以将其描绘成把三维向量“压平”到平面上。删除z分量会使向量的深度消失
def component(v,direction):
    return (np.dot(v,direction) / length(direction))


# 从三个坐标向下投影到两个坐标的方法。
# 这个函数接收一个三维向量或三个数组成的元组，并返回一个二维向量或两个数组成的元组。
def vector_to_2d(v):
    vx_2d = component(v,np.array([1,0,0]))
    vy_2d=component(v,np.array([0,1,0]))
    return np.array([vx_2d,vy_2d] )


def face_to_2d(face):
    return [vector_to_2d(vertex) for vertex in face]

def scale_by(n):
    def scale(vector):
        return vector*n
    return scale

def move_to(x,y):
    def move(vector):
        vx,vy = vector[0],vector[1]
        return np.array([x/2+x*vx/4,y/2-y*vy/4])
    return move

def combine(f1,f2):
#    result = lambda v:v
#    for f in args:
#        result = lambda v: f(result(v))
#    return result
    return lambda v: f2(f1(v))

def to_polar_coordinates(vector):
    alpha = atan2(vector[1],vector[0])
    v_length = length(vector)
    return (v_length,alpha)

def to_cartesian_coordinates(v_length,alpha):

    return np.array([v_length*cos(alpha),v_length*sin(alpha)])

def rotate_around_z_by_degree(degree):

    radian = np.deg2rad(degree) #/180*pi

    def rotate_around_z( vector):
        
        vx,vy,vz = vector
        v_length,alpha = to_polar_coordinates(np.array([vx,vy]))
        # 旋转之后的弧度
        rotated_radian = alpha + radian
        rotated_x,rotated_y = to_cartesian_coordinates(v_length,rotated_radian)
        
        return np.array([rotated_x,rotated_y,vz])
    
    return rotate_around_z

def rotate_around_x_by_degree(degree):

    radian = np.deg2rad(degree) #/180*pi

    def rotate_around_x( vector):
        
        vx,vy,vz = vector
        v_length,alpha = to_polar_coordinates(np.array([vy,vz]))
        # 旋转之后的弧度
        rotated_radian = alpha + radian
        rotated_y,rotated_z = to_cartesian_coordinates(v_length,rotated_radian)
        
        return np.array([vx,rotated_y,rotated_z])
    
    return rotate_around_x

def rotate_around_y_by_degree(degree):

    radian = np.deg2rad(degree) #/180*pi

    def rotate_around_y( vector):
        
        vx,vy,vz = vector
        v_length,alpha = to_polar_coordinates(np.array([vx,vz]))
        # 旋转之后的弧度
        rotated_radian = alpha + radian
        rotated_x,rotated_z = to_cartesian_coordinates(v_length,rotated_radian)
        
        return np.array([rotated_x,vy,rotated_z])
    
    return rotate_around_y

def to_unit_vector(vector):
    """将一个向量压缩为单位向量的过程称为“归一化”或“标准化”。
    通过将向量除以其长度（模）来获得单位向量，使得该向量的长度变为1"""
    return vector/np.linalg.norm(vector)